package org.cos.generation.epda;

import java.util.List;
import java.util.Set;

import org.cos.generation.util.agorithm.MergeState;
import org.cos.generation.util.agorithm.NullTransitionRemoving;
import org.cos.generation.util.agorithm.Reachedable;
import org.cos.generation.util.agorithm.CustomCallSquelching;
import org.cos.generation.util.agorithm.Tarjan;
import org.cos.generation.util.info.ClassInfo;

public class EPDAOptimizer {
	
	/**
	 * Reduce the null transitions for a list of EPDAs.
	 * @param classArray
	 */
	public static void nullTransReduce(List<ClassInfo> classList) {
		for (ClassInfo classInfo : classList) {
			EPDA epda = classInfo.getEPDA();
			// Copy states.
			int stateSize = epda.getStateSize();
			State[] states = new State[stateSize]; 
			epda.getStates().toArray(states);
			
			// Find null transition strongly connected component.
			Tarjan tarjan = new Tarjan();
			int[] sccRoot = tarjan.tarjan(states);

			// Merge the equivalent states.			
			MergeState mergeState = new MergeState();
			mergeState.mergeState(states, sccRoot);

			// Find null transition reachedable states for every state.
			Reachedable reachedable = new Reachedable();
			List<Set<Integer>> reachedList = reachedable.nullReachedable(states);
			
			// Remove the null transitions and unreachable states.
			stateSize = NullTransitionRemoving.remove(states, reachedList);
			
			// Restore the states to EPDA.
			epda.clear();
			epda.addStates(stateSize, states);
		}
	}
	
	/**
	 * Squech custom call for a list of EPDAs.
	 * @param classArray
	 */
	public static void customCallSquelch(List<ClassInfo> classList) {
		for (ClassInfo classInfo : classList) {
			CustomCallSquelching squelcher = new CustomCallSquelching();
			squelcher.squelch(classInfo);
		}
	}
		
}
